package com.apes.scm.advanceOrder.service;

import com.apes.framework.api.DomainService;
import com.apes.framework.jpa.spec.JpaDsl;
import com.apes.framework.plugin.esb.api.SimpleRequest;
import com.apes.framework.util.MapUtil;
import com.apes.scm.account.account.model.Stock;
import com.apes.scm.account.account.repository.StockRepository;
import com.apes.scm.advanceOrder.model.AdvanceSalePlan;
import com.apes.scm.advanceOrder.model.AdvanceSalePlanItem;
import com.apes.scm.advanceOrder.repository.AdvanceSalePlanItemRepository;
import com.apes.scm.advanceOrder.repository.AdvanceSalePlanRepository;
import com.apes.scm.masterdata.stock.model.Location;
import com.apes.scm.masterdata.stock.repository.LocationRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @ClassName AdvanceSalePlanService
 * @Description TODO
 * @Author pengyb
 * @Date 2018/12/12 10:50
 * @Version 1.0
 **/
@Service("advanceSalePlanService")
public class AdvanceSalePlanService extends DomainService {
    @Autowired
    private AdvanceSalePlanRepository advanceSalePlanRepository;

    @Autowired
    public LocationRepository locationRepository;

    @Autowired
    StockRepository stockRepository;

    /**
     * 新增预售单
     *
     * @param request
     * @return AdvanceSalePlan
     * @throws RuntimeException
     */
    public AdvanceSalePlan create(SimpleRequest request) throws RuntimeException {
        AdvanceSalePlan advanceSalePlan = request.getO(AdvanceSalePlan.class);
        DateFormat format = new SimpleDateFormat("yyyy-MM-dd");
        String validFromStr=format.format(advanceSalePlan.getValidFrom());
        String validPeriodStr=format.format(advanceSalePlan.getValidPeriod());
        LocalDate today = LocalDate.now();
        DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-MM-dd");
        LocalDate validFrom = LocalDate.parse(validFromStr, dtf);   //有效期起
        LocalDate validPeriod=LocalDate.parse(validPeriodStr,dtf);  //有效期止

        if (today.equals(validPeriod)) throw  new RuntimeException("有效期止日期不能是当前日期");
        if (today.isAfter(validFrom)) throw  new RuntimeException("有效期起日期不能在当前日期前");
        if (validFrom.isAfter(validPeriod))throw new RuntimeException("有效期止日期不能在有效期起日期前");
        advanceSalePlan.setState("sent");
        if (advanceSalePlan.getCreateDate() == null) {
            advanceSalePlan.setCreateDate(new Date());
        } else {
            advanceSalePlan.setUpdateDate(new Date());
        }

        return advanceSalePlanRepository.saveAndFlush(advanceSalePlan);
    }

    /**
     * 修改预售单
     *
     * @param request
     * @return
     * @throws RuntimeException
     */
    public AdvanceSalePlan update(SimpleRequest request) throws RuntimeException {
        checkData(request);
        AdvanceSalePlan advanceSalePlan = request.getO(AdvanceSalePlan.class);
//        advanceSalePlan.setState("sent");
        return advanceSalePlanRepository.saveAndFlush(advanceSalePlan);
    }

    /**
     * 删除预售单
     *
     * @param request
     * @return
     * @throws RuntimeException
     */
    public String delete(SimpleRequest request) throws RuntimeException {
        checkData(request);
        AdvanceSalePlan advanceSalePlan = request.getO(AdvanceSalePlan.class);
        advanceSalePlanRepository.delete(advanceSalePlan.getId());
        return "删除成功";
    }

    /**
     * 审核预售单
     *
     * @param request
     * @return
     * @throws RuntimeException
     */
    public AdvanceSalePlan approve(SimpleRequest request) throws RuntimeException {
        checkData(request);
        AdvanceSalePlan advanceSalePlan = request.getO(AdvanceSalePlan.class);
        advanceSalePlan.setState("approve");
        advanceSalePlan.setApproveUid(this.getPerson(request));
        advanceSalePlan.setApproveDate(new Date());
        return advanceSalePlanRepository.saveAndFlush(advanceSalePlan);
    }

    /**
     * 执行预售单
     *
     * @param request
     * @return
     * @throws RuntimeException
     */
    public AdvanceSalePlan executive(SimpleRequest request) throws RuntimeException {
        AdvanceSalePlan advance = advanceSalePlanRepository.findOne((String) request.get("id"));
        if (advance.getApproveDate() == null) throw new RuntimeException("未审核!");

        AdvanceSalePlan advanceSalePlan = request.getO(AdvanceSalePlan.class);
        Location location = advanceSalePlan.getLocation();
        Set<AdvanceSalePlanItem> items = advanceSalePlan.getAdvanceSalePlanItems();

        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        String validFrom = sdf.format(advanceSalePlan.getValidFrom());
        LocalDate today = LocalDate.now();
        DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-MM-dd");
        LocalDate parse = LocalDate.parse(validFrom, dtf);

        if (today.equals(parse)) { //是否是当前日期{ture:执行;false:定时执行}
            items.forEach((item) -> {
                List<Stock> stocks = stockRepository.findAll(JpaDsl.toCriteria(MapUtil.mapper("location", location, "product", item.getProduct())));
                if (stocks.isEmpty()) throw new RuntimeException("此库区无此商品");
                stocks.forEach((stock -> {
                    if (stock.getSalesControlQty() == 0)
                        throw new RuntimeException("商品:" + item.getProduct().getName() + "没有库存了!");
                    if (stock.getSalesControlQty() != 0 && (stock.getSalesControlQty() - item.getSalesControlQty()) < 0)
                        throw new RuntimeException("商品:" + item.getProduct().getName() + "库存数量不足!尚缺" + (item.getSalesControlQty() - stock.getSalesControlQty()) + "单位");
                    stock.setSalesControlQty(stock.getSalesControlQty() - item.getSalesControlQty());
                    stockRepository.saveAndFlush(stock);
                }));
            });
            advanceSalePlan.setState("done");
        } else if (today.isBefore(parse)) { //是否在当前日期之后
            advanceSalePlan.setState("executing");

        } else if (today.isAfter(parse)) throw new RuntimeException("当前日期已超出生效日期！请检查！");
        advanceSalePlan.setApproveUid(this.getPerson(request));
        advanceSalePlan.setApproveDate(new Date());
        return advanceSalePlanRepository.saveAndFlush(advanceSalePlan);
    }

    /**
     * 定时任务(执行，增减商品库存)
     */
    public void timing() throws RuntimeException {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        LocalDate today = LocalDate.now(); //当前日期
        DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-MM-dd");

        List<AdvanceSalePlan> advanceSalePlans = advanceSalePlanRepository.findAll(); //查出所有预售单
        advanceSalePlans.stream().filter(aps -> aps.getState().equals("done") || aps.getState().equals("executing")).collect(Collectors.toList()).forEach(advanceSalePlan -> { //遍历选中状态的单

            LocalDate parse = LocalDate.parse(sdf.format(advanceSalePlan.getValidFrom()), dtf);//有效期起日期
            LocalDate stopDate = LocalDate.parse(sdf.format(advanceSalePlan.getValidPeriod()), dtf);//有效起止日期

            Set<AdvanceSalePlanItem> items = advanceSalePlan.getAdvanceSalePlanItems();
            Location location = advanceSalePlan.getLocation();

            if (today.equals(stopDate)) {//有效日期止是否是当前日期{ture:执行;false:定时执行}
                items.forEach((item) -> {
                    List<Stock> stocks = stockRepository.findAll(JpaDsl.toCriteria(MapUtil.mapper("location", location, "product", item.getProduct())));
                    if (stocks.isEmpty()) throw new RuntimeException("此库区无此商品");
                    stocks.forEach((stock) -> {
                        stock.setSalesControlQty(stock.getSalesControlQty() + item.getSalesControlQty());
                        stockRepository.saveAndFlush(stock);
                    });
                });
                advanceSalePlan.setState("repeal");  //有效期止，自动终止
                advanceSalePlanRepository.saveAndFlush(advanceSalePlan);
            }
            if (advanceSalePlan.getState().equals("executing")) {
                if (today.equals(parse)) { //有效日期起是否是当前日期{ture:执行;false:定时执行}
                    items.forEach((item) -> {
                        List<Stock> stocks = stockRepository.findAll(JpaDsl.toCriteria(MapUtil.mapper("location", location, "product", item.getProduct())));
                        if (stocks.isEmpty()) throw new RuntimeException("此库区无此商品");
                        stocks.forEach((stock -> {
                            if (stock.getSalesControlQty() == 0)
                                throw new RuntimeException("商品:" + item.getProduct().getName() + "没有库存了!");
                            if (stock.getSalesControlQty() != 0 && (stock.getSalesControlQty() - item.getSalesControlQty()) < 0)
                                throw new RuntimeException("商品:" + item.getProduct().getName() + "库存数量不足!尚缺" + (item.getSalesControlQty() - stock.getSalesControlQty()) + "单位");
                            stock.setSalesControlQty(stock.getSalesControlQty() - item.getSalesControlQty());
                            stockRepository.saveAndFlush(stock);
                        }));
                    });
                }
                advanceSalePlan.setState("done"); //有效期起,自动执行
                advanceSalePlanRepository.saveAndFlush(advanceSalePlan);
            }


        });


    }

    /**
     * 终止预售单
     *
     * @param request
     * @return
     * @throws RuntimeException
     */
    public AdvanceSalePlan cancle(SimpleRequest request) throws RuntimeException {
        AdvanceSalePlan advanceSalePlans = advanceSalePlanRepository.findOne((String) request.get("id"));
        if (advanceSalePlans == null) throw new RuntimeException("预售单：" + request.get("id") + "在系统中不存在！");
        if (advanceSalePlans.getVersion() != (int) request.get("version")) throw new RuntimeException("记录已更新或已删除！");
        AdvanceSalePlan advanceSalePlan = request.getO(AdvanceSalePlan.class);
        Location location = advanceSalePlan.getLocation();
        Set<AdvanceSalePlanItem> advanceSalePlanItems = advanceSalePlan.getAdvanceSalePlanItems();
        if (advanceSalePlan.getState().equals("done")) {  //终止状态为已执行的单
            advanceSalePlanItems.forEach(advanceSalePlanItem -> {
                List<Stock> stocks = stockRepository.findAll(JpaDsl.toCriteria(MapUtil.mapper("location", location, "product", advanceSalePlanItem.getProduct())));
                if (stocks.isEmpty()) throw new RuntimeException("此库区无此商品,已被修改或已删除！");
                stocks.forEach(stock -> {
                    stock.setSalesControlQty(stock.getSalesControlQty() + advanceSalePlanItem.getSalesControlQty());
                    stockRepository.saveAndFlush(stock);
                });
            });
        }
        advanceSalePlan.setState("repeal");
        advanceSalePlan.setRepealUid(this.getPerson(request));
        advanceSalePlan.setRepealDate(new Date());
        return advanceSalePlanRepository.saveAndFlush(advanceSalePlan);
    }


    /**
     * 检查
     *
     * @param request
     */
    public void checkData(SimpleRequest request) {
        AdvanceSalePlan advanceSalePlans = advanceSalePlanRepository.findOne((String) request.get("id"));
        if (advanceSalePlans == null) throw new RuntimeException("预售单：" + request.get("id") + "在系统中不存在！");
        if (advanceSalePlans.getVersion() != (int) request.get("version")) throw new RuntimeException("记录已更新或已删除！");
        if (advanceSalePlans.getApproveDate() != null) throw new RuntimeException("已审核!");
        AdvanceSalePlan advanceSalePlan = request.getO(AdvanceSalePlan.class);
        DateFormat format = new SimpleDateFormat("yyyy-MM-dd");
        String validFromStr=format.format(advanceSalePlan.getValidFrom());
        String validPeriodStr=format.format(advanceSalePlan.getValidPeriod());
        LocalDate today = LocalDate.now();
        DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-MM-dd");
        LocalDate validFrom = LocalDate.parse(validFromStr, dtf);   //有效期起
        LocalDate validPeriod=LocalDate.parse(validPeriodStr,dtf);  //有效期止

       // if(validFrom.equals(validPeriod))throw  new RuntimeException("有效期起日期不能和有效期止日期在同一天，这毫无意义");
        if (today.equals(validPeriod)) throw  new RuntimeException("有效期止日期不能是当前日期");
        if (today.isAfter(validFrom)) throw  new RuntimeException("有效期起日期不能在当前日期前");
        if (validFrom.isAfter(validPeriod))throw new RuntimeException("有效期止日期不能在有效期起日期前");

    }

}
